package com.boat.starter.satoken.config;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.boat.framework.base.exception.CommonErrorCode;
import com.boat.framework.base.exception.ServiceException;
import com.boat.framework.common.util.StringUtils;
import com.boat.starter.satoken.config.props.AuthProperties;
import com.boat.starter.satoken.config.props.AuthProperties.SaTokenProperties;
import com.boat.starter.satoken.constant.AuthConsts;
import com.boat.starter.satoken.core.dao.PlusSaTokenDao;

import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * sa-token 配置
 *
 * @author 周江
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(AuthProperties.class)
@ConditionalOnProperty(prefix = AuthConsts.PREFIX, value = "type", havingValue = AuthConsts.AuthType.SATOKEN)
@RequiredArgsConstructor
public class SaTokenAutoConfiguration implements InitializingBean, WebMvcConfigurer {
	
	private final AuthProperties authProperties;
	
	@Bean
	@Primary
	public SaTokenConfig getSaTokenConfigPrimary() {
		SaTokenProperties saTokenProperties = authProperties.getSatoken();
		SaTokenConfig config = new SaTokenConfig();
		config.setTokenName(saTokenProperties.getTokenName());
		config.setTimeout(saTokenProperties.getTimeout());
		config.setTokenPrefix(saTokenProperties.getTokenPrefix());
		config.setDynamicActiveTimeout(saTokenProperties.isDynamicActiveTimeout());
		config.setIsReadBody(saTokenProperties.isReadBody());
		config.setIsReadCookie(saTokenProperties.isReadCookie());
		config.setJwtSecretKey(saTokenProperties.getJwtSecretKey());
		// 取消启动时打印satoken字画
		config.setIsPrint(false);
		return config;
	}

	@Bean
	public StpLogic getStpLogicJwt() {
		// Sa-Token 整合 jwt (简单模式)
		return new StpLogicJwtForSimple();
	}

	/**
	 * 权限接口实现(暂时不需要此功能)
	 */
//    @Bean
//    public StpInterface stpInterface() {
//        return new SaPermissionImpl();
//    }

	/**
	 * 自定义dao层存储
	 */
	@Bean
	public SaTokenDao saTokenDao() {
		return new PlusSaTokenDao();
	}
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new SaInterceptor(handle -> {
			// 检查是否登录 是否有token
        	if (!StpUtil.isLogin()) {
				throw new ServiceException(CommonErrorCode.AUTH_USER_NO_LOGIN);
			}
		})).addPathPatterns("/**").excludePathPatterns(excludePaths());
	}
	
	private List<String> excludePaths() {
		List<String> excludeList = new ArrayList<>(100);
		excludeList.addAll(StringUtils.str2List(authProperties.getSatoken().getCommonExcludes(), ",", true,true));
		excludeList.addAll(StringUtils.str2List(authProperties.getSatoken().getExcludes(), ",", true,true));
		log.info("auth excludePaths:{}", excludeList);
		return excludeList;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		log.info("boat-starter-satoken加载成功");
	}

}
